#include "MainWindow.h"
#include "ui_mainwindow.h"
#include <QtGui>
#include <iostream>
#include "SoundSample.h"
#include "SoundSampleAIFF.h"
#include "SoundSampleWAV.h"
#include "SoundSampleMP3.h"
#include <QtConcurrentRun>

using namespace std;

// setup MainWindow
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), listOfAllSamples(NULL), model(NULL)
{
    ui->setupUi(this);

	// create the Singleton instance of the SoundPlayer here
	this->player = SoundPlayer::getInstance();
	
    // Connect the buttons to the corresponding SLOT
	// playback controls
    connect( ui->playButton, SIGNAL(clicked()), player->getPlayerObject(), SLOT(play()));
    connect( ui->stopButton, SIGNAL(clicked()), player->getPlayerObject(), SLOT(pause()));
	connect( ui->rtzButton, SIGNAL(clicked()), player->getPlayerObject(), SLOT(stop()));
	
	// menu and sample select box
	connect( ui->actionAdd_Sample_Folder, SIGNAL(triggered()), this, SLOT(addFiles()));
	connect( ui->sampleList, SIGNAL(clicked(QModelIndex)), this, SLOT(drawWaveform(QModelIndex)));

    // Just one item can be selected at a time
    ui->sampleList->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->sampleList->setSelectionBehavior(QAbstractItemView::SelectRows);
	
	// disable the Play and Stop buttons
	ui->playButton->setEnabled(false);
	ui->stopButton->setEnabled(false);
	ui->rtzButton->setEnabled(false);
	
	// connect the tick signal from the audio player to the timeDisplay label slot
	connect( player->getPlayerObject(), SIGNAL(tick(qint64)), this, SLOT(setCurrentPos(qint64)));
	
	// define the playStop shortcut to work in the whole widget
	playStop = new QShortcut(this);
	playStop->setKey(Qt::Key_Space);
	
	// connect 
	connect( playStop, SIGNAL(activated()), player, SLOT(playStopKey()));
}

// add Files from folders to the list
void MainWindow::addFiles(){

    QDir directory(QFileDialog::getExistingDirectory(this, tr("Select Folder containing the samples")));

    QStringList fileFilter;
    fileFilter << tr("*.wav") << tr("*.aif") << tr("*.aiff") << tr(".aifc") << tr("*.mp3");

    QStringList fileList = directory.entryList(fileFilter);
    int fileCount = fileList.size();

    if ( fileCount == 0 )
    {
        return;
    }

    QStringList fileInfo;
    fileInfo << "Description" << "Length" << "Format" << "Bit" << "Ch" << "Samplerate" << "Filename" << "Filesize";

    // Model for data supply to the ListView
    this->model = new QStandardItemModel( fileCount, 8, this);
	
    model->setHorizontalHeaderLabels(fileInfo);

    this->listOfAllSamples = new QList<SoundSample*>();

    // get all the files from the selected folder and gather their meta data
    for (int i = 0; i < fileCount; i++)
    {
        QString filePath = directory.absolutePath() + QDir::separator() + fileList.at(i);

        // determine which kind of sample it is and make an object of the right one
        SoundSample * temp = NULL;

        // WAV
        if ( filePath.endsWith ( "wav", Qt::CaseInsensitive ))
        {
            temp = new SoundSampleWAV(filePath);
        }
		
        // AIFF
        else if ( (filePath.endsWith ("aiff", Qt::CaseInsensitive))
            || (filePath.endsWith("aif", Qt::CaseInsensitive))
            || (filePath.endsWith("aifc", Qt::CaseInsensitive)))
        {
            temp = new SoundSampleAIFF(filePath);
        }
		
        // MP3
        else if ( filePath.endsWith ("mp3", Qt::CaseInsensitive))
        {
            temp = new SoundSampleMP3(filePath);
        }

        // get the meta information from the file
        temp->getFileReadBehavior()->gatherMetaInformation(temp);
        temp->setFilename(fileList.at(i));
        listOfAllSamples->append(temp);
        
        model->setItem(i,0, new QStandardItem(temp->getDescription()));
		model->setItem(i,1, new QStandardItem(temp->getLength()));
		model->setItem(i,2, new QStandardItem(temp->getFileformat()));
		model->setItem(i,3, new QStandardItem(temp->getBitdepth()));					 
		model->setItem(i,4, new QStandardItem(temp->getChannels()));
		model->setItem(i,5, new QStandardItem(temp->getSamplerate()));
		model->setItem(i,6, new QStandardItem(temp->getFilename()));
		model->setItem(i,7, new QStandardItem(temp->getFilesize()));
                
    }

    // Set the model to the sampleList View
    ui->sampleList->setModel(model);

    // set the row height for the whole table
    for (int i=0; i < fileCount; i++)
    {
        ui->sampleList->setRowHeight(i, 20);
    }

    // Preset column widths.
    // User can change it afterwards to fit his needs
    // --------------------------------------------------------------
    // Description
    ui->sampleList->setColumnWidth(0, 400);
    // Length
    ui->sampleList->setColumnWidth(1, 50);
    // File Format
    ui->sampleList->setColumnWidth(2, 50);
    // Bitdepth
    ui->sampleList->setColumnWidth(3, 30);
    // Channels
    ui->sampleList->setColumnWidth(4, 30);
    // Samplerate
    ui->sampleList->setColumnWidth(5, 80);
	// File Name
	ui->sampleList->setColumnWidth(6, 250);
	// File Size
	ui->sampleList->setColumnWidth(7, 50);

 }

// slot function : gets called on a click in the list
// calculates the waveform for the audio file and loads it into the player
void MainWindow::drawWaveform(QModelIndex index)
{
	// enable the buttons
	if( !(ui->playButton->isEnabled()))
	{
		ui->playButton->setEnabled(true);
		ui->stopButton->setEnabled(true);
		ui->rtzButton->setEnabled(true);
	}
	
    //std::cout << "draw Waveform" << index.row() << std::endl;
    SoundSample* temp = this->listOfAllSamples->at(index.row());
	
    // set the file to be playable by the soundplayer
    this->player->setAudiofile(temp->getFilepath());
	
	QProgressDialog * progressDialog = new QProgressDialog(this);
	progressDialog->setRange(0, 100);
	progressDialog->setWindowTitle(tr("Find Files"));
	progressDialog->setWindowModality(Qt::WindowModal);
	progressDialog->setMinimumDuration(200);
	
	// connect the signals and slots to update the progress bar
	connect(temp->getFileReadBehavior(), SIGNAL(percentFinished(int)), progressDialog , SLOT(setValue(int)));

	QFuture<void> result = QtConcurrent::run(temp->getFileReadBehavior(), &IFileReadBehavior::calculateWaveform, temp, ui->waveformView->width());
	// calculation in separate thread !!! FIX IT
	result.waitForFinished();
	
	//temp->getFileReadBehavior()->calculateWaveform(temp, ui->waveformView->width());
	
	// commit the calculated waveform to be drawn
	ui->waveformView->setMaxBitdepthValue(temp->getBitdepth().toInt());
    ui->waveformView->setPlotDataUp(temp->getPlotDataUp());
	ui->waveformView->setPlotDataDown(temp->getPlotDataDown());
}

// this function gets triggered all the time with the position of
// the audio player ( even if not running
void MainWindow::setCurrentPos(qint64 millis)
{
	ostringstream stream;
	stream << millis; 
	
	ui->timeDisplay->setText(QString(stream.str().c_str()));
	
	// get the position of the cursor within the widget
	QPoint cursorPos = ui->waveformView->getCursorWidget()->pos();
	
	// calculate the position according to the position within the track
	//std:: cout << "State : " << this->player->getPlayerObject()->state() << endl;
	
	Phonon::State state = this->player->getPlayerObject()->state();
	
	if( state == Phonon::ErrorState || state == Phonon::LoadingState)
	{
		return;
	}
		
	qint64 totalTime = this->player->getPlayerObject()->totalTime();
	int x_pos = (millis * ui->waveformView->width()) / totalTime;
	
	// set the position to the widget
	ui->waveformView->getCursorWidget()->move(x_pos, cursorPos.y());
}

MainWindow::~MainWindow()
{
    if (listOfAllSamples)
    {
        delete listOfAllSamples;
    }

    if (model)
    {
        delete model;
    }

    delete ui;
}
